from decimal import Decimal

from django.utils.timezone import now
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.permissions import IsAuthenticated
from django_redis import get_redis_connection
# Create your views here.
from goods.models import SKU

from mall import settings
from .serializers import OrdersPlaceSerializer
from .models import OrderInfo,OrderGoods
from users.models import Address
from django.db import transaction


class OrdersPlaceView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self,request):

        #获取用户信息
        user = request.user

        redis = get_redis_connection('cart')

        cart_redis = redis.hgetall('cart_%s'%user.id)  #{b'3':b'1',b'16':b'1'}
        cart_selected = redis.smembers('cart_selected_%s'%user.id) #[b'16']

        cart={}
        for id in cart_selected:
            cart[int(id)] = int(cart_redis[id])


        skus = SKU.objects.filter(pk__in=cart.keys())

        for sku in skus:
            sku.count = cart[sku.id]

        nFreight = Decimal(10.00)

        serializer = OrdersPlaceSerializer({'freight':nFreight,'skus':skus})

        return Response(serializer.data)



        # {
        #     "freight": "10.00",
        #     "skus": [
        #         {
        #             "id": 10,
        #             "name": "华为 HUAWEI P10 Plus 6GB+128GB 钻雕金 移动联通电信4G手机 双卡双待",
        #             "default_image_url": "http://image.meiduo.site:8888/group1/M00/00/02/CtM3BVrRchWAMc8rAARfIK95am88158618",
        #             "price": "3788.00",
        #             "count": 1
        #         },
        #         {
        #             "id": 16,
        #             "name": "华为 HUAWEI P10 Plus 6GB+128GB 曜石黑 移动联通电信4G手机 双卡双待",
        #             "default_image_url": "http://image.meiduo.site:8888/group1/M00/00/02/CtM3BVrRdPeAXNDMAAYJrpessGQ9777651",
        #             "price": "3788.00",
        #             "count": 1
        #         }
        #     ]
        # }

class OrdersSaveView(APIView):
    permission_classes = [IsAuthenticated]

    def post(self,request):
        address = request.data.get('address')
        pay_method = request.data.get('pay_method')

        if not (address and pay_method):
            return Response(status=status.HTTP_400_BAD_REQUEST)
        try:
            addr = Address.objects.get(pk=address)
        except Exception:
            return Exception('获取收货地址数据错误')

        try:
            user = request.user
        except Exception:
            return Response(status=status.HTTP_400_BAD_REQUEST)

        order_id = now().strftime('%Y%m%d%H%M%S')+('%09d'%user.id)
        redis = get_redis_connection('cart')

        with transaction.atomic():
            save_point = transaction.savepoint() #开启事物，创建数据保存点

            try:
                #保存订单基本信息
                order = OrderInfo.objects.create(
                    order_id = order_id,
                    user = user,
                    address = addr,
                    pay_method = pay_method,
                    total_count = 0,
                    total_amount = Decimal('0'),
                    freight = Decimal('0.0'),
                    status = OrderInfo.ORDER_STATUS_ENUM['UNPAID'] if int(pay_method)==OrderInfo.PAY_METHODS_ENUM['ALIPAY'] else OrderInfo.ORDER_STATUS_ENUM['UNSEND']
                )

                #保存订单中商品的基本信息


                try:
                    cart_id_count = redis.hgetall('cart_%s'%user.id,)
                    cart_selected = redis.smembers('cart_selected_%s'%user.id)
                except Exception:
                    transaction.savepoint_rollback(save_point)
                    raise Exception('读取订单数据失败！')

                cart_redis = {}
                for id in cart_selected:
                    cart_redis[int(id)] = int(cart_id_count[id])


                skus = SKU.objects.filter(pk__in=cart_redis.keys())

                for sku in skus:
                    while True:
                        count = cart_redis[sku.id]
                        #判断商品库存是否满足订量
                        if sku.stock < count:
                            transaction.savepoint_rollback(save_point)
                            raise Exception('库存不足')


                        #如果满足需求量，修改库存量和销售量
                        # sku.stock -= count
                        # sku.sales += count
                        # sku.save()

                        #增加乐观锁，防止高并发更新数据时出错
                        origin_stock = sku.stock
                        origin_sales = sku.sales
                        new_stock = sku.stock-count
                        new_sales = sku.sales+count

                        ret = SKU.objects.filter(id = sku.id,stock=origin_stock).update(
                            stock = new_stock,
                            sales = new_sales
                        )
                        if ret==0:
                            continue


                        order.total_count = count
                        order.total_amount = sku.price*count


                        OrderGoods.objects.create(
                            order = order,
                            sku = sku,
                            count = count,
                            price = sku.price
                        )
                        break
                order.save()
            except Exception:
                transaction.savepoint_rollback(save_point)
                raise Exception('下单失败！')
            transaction.savepoint_commit(save_point)

        pl = redis.pipeline()
        pl.hdel('cart_%s'%user.id,*cart_selected)
        pl.srem('cart_selected_%s'%user.id,*cart_selected)
        pl.execute()

        return Response({'order_id':order_id})










